package com.benzhitech.tcp;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * TCP 服务器处理器
 * 处理 TCP 连接和消息
 */
public class TcpServerHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(TcpServerHandler.class);
    
    // 存储所有活跃连接，key 是连接 ID，value 是 ChannelHandlerContext
    private static final ConcurrentMap<String, ChannelHandlerContext> activeConnections = new ConcurrentHashMap<>();
    
    /**
     * 当建立连接时调用
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String connectionId = ctx.channel().id().asShortText();
        activeConnections.put(connectionId, ctx);
        log.info("设备连接已建立: ID={}, 远程地址={}", connectionId, ctx.channel().remoteAddress());
        
        // 发送欢迎消息
        String welcomeMsg = "欢迎连接到 Tiny TCP 服务器!";
        ctx.writeAndFlush(ctx.alloc().buffer().writeBytes(welcomeMsg.getBytes(StandardCharsets.UTF_8)));
    }
    
    /**
     * 当连接断开时调用
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String connectionId = ctx.channel().id().asShortText();
        activeConnections.remove(connectionId);
        log.info("设备连接已断开: ID={}, 远程地址={}", connectionId, ctx.channel().remoteAddress());
    }
    
    /**
     * 当收到消息时调用
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String connectionId = ctx.channel().id().asShortText();
        
        if (msg instanceof ByteBuf) {
            ByteBuf buf = (ByteBuf) msg;
            try {
                // 读取消息内容
                byte[] bytes = new byte[buf.readableBytes()];
                buf.readBytes(bytes);
                String message = new String(bytes, StandardCharsets.UTF_8);
                
                log.info("收到 TCP 消息: ID={}, 消息={}", connectionId, message);
                
                // 简单的回显处理
                String response = "Echo: " + message;
                ctx.writeAndFlush(ctx.alloc().buffer().writeBytes(response.getBytes(StandardCharsets.UTF_8)));
                
                // 可以调用业务处理器来处理接收到的消息
                // TcpMessageProcessor.process(connectionId, message);
            } finally {
                buf.release(); // 确保释放 ByteBuf
            }
        } else {
            log.warn("收到未知类型的消息: {}", msg.getClass().getName());
            ctx.fireChannelRead(msg);
        }
    }
    
    /**
     * 当发生异常时调用
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        String connectionId = ctx.channel().id().asShortText();
        log.error("TCP 连接发生异常: ID={}", connectionId, cause);
        ctx.close();
    }
    
    /**
     * 发送消息到指定的连接
     *
     * @param connectionId 连接 ID
     * @param message 要发送的消息
     * @return 是否发送成功
     */
    public static boolean sendMessage(String connectionId, String message) {
        ChannelHandlerContext ctx = activeConnections.get(connectionId);
        if (ctx != null && ctx.channel().isActive()) {
            ByteBuf buf = ctx.alloc().buffer().writeBytes(message.getBytes(StandardCharsets.UTF_8));
            ctx.writeAndFlush(buf);
            log.info("消息发送成功: ID={}, 消息={}", connectionId, message);
            return true;
        } else {
            log.warn("无法发送消息，连接不存在或已关闭: ID={}", connectionId);
            return false;
        }
    }
    
    /**
     * 获取所有活跃连接的 ID
     *
     * @return 活跃连接 ID 数组
     */
    public static String[] getActiveConnectionIds() {
        return activeConnections.keySet().toArray(new String[0]);
    }
    
    /**
     * 获取活跃连接数量
     *
     * @return 活跃连接数量
     */
    public static int getActiveConnectionCount() {
        return activeConnections.size();
    }
    
    /**
     * 断开指定的连接
     *
     * @param connectionId 连接 ID
     * @return 是否成功断开
     */
    public static boolean disconnectConnection(String connectionId) {
        ChannelHandlerContext ctx = activeConnections.get(connectionId);
        if (ctx != null) {
            ctx.close();
            log.info("已主动断开连接: ID={}", connectionId);
            return true;
        } else {
            log.warn("无法断开连接，连接不存在: ID={}", connectionId);
            return false;
        }
    }
} 